home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / Dots & Pixels / headers / flowdots.h < prev    next >
C/C++ Source or Header  |  1995-09-29  |  5KB  |  165 lines

  1. #pragma once
  2. //
  3. // class flowdots is used for the rapid appliance of first order optic
  4. // flow to large numbers of dots. A large speed increases is obtained by performing
  5. // many operations in integers. At the same time the interface to the class uses
  6. // doubles for ease of use.
  7. // We store coordinates of dots in 16-bit signed fixed point format with an implied
  8. // decimal point after the second bit. This limits the values of the numbers used
  9. // to the range (-2.0, +2.0) (boundaries excluded)
  10. //
  11. // Two copies of the actual parameters of the flow are kept:
  12. //
  13. //        1. The user accessible ones, in doubles, and in degrees and per second
  14. //        2. A copy in fixed-point quantities, in 'per stimulus frame period'
  15. //
  16. // The user can set 1. directly.
  17. // When how_often (see below) is unequal to zero a call to 'changed()' computes 2.
  18. // When how_often is zero, 2. is recomputed by every call to 'apply_flow', which
  19. // is called by 'screendots::make_a_move'
  20. //
  21. // The translation from per-second parameters, as specified in the flowsettings
  22. // (copy 1) to per-frame coordinates (copy 2), takes place via one of two methods.
  23. // Firstly the user can call the constructor with how_often == 0 (or later call
  24. // 'set_how_often()' to set it to zero). If this is done the routine keeps track of
  25. // the time taken between subsequent calls of 'apply_flow' and scales the
  26. // displacements accordingly. Alternatively when 'how_often' is unequal to zero it
  27. // is assumed to signify the frequency (in Hz) with which 'apply_flow' gets called.
  28. //
  29. // Note that it generally is faster to explicitly set 'how_often' to something non-zero.
  30. //
  31. #define degrees * 0.0174532925199
  32. #define degrees_per_second * 0.0174532925199
  33. //
  34. // 950502: deriving flowdots from 'flowparams'. This allows one to switch
  35. // between different flow parameters at high speed, i.e. without having to
  36. // call 'changed()'. One can now do:
  37. //
  38. //    flowdots fd( 8, 100, 100, 1000, 10, 75.0);
  39. //    fd.rotation = 20;
  40. //    fd.changed();
  41. //    const flowparams rot_params = fd;
  42. //
  43. //    fd.rotation = 0;
  44. //    fd.expansion = 1.1;
  45. //    fd.changed();
  46. //    const flowparams div_params = fd;
  47. //
  48. //    while( !done)
  49. //    {
  50. //        fd.setsettings( rot_params);
  51. //        fd.make_a_move();
  52. //        fd.setsettings( div_params);
  53. //        fd.make_a_move();
  54. //    }
  55. //
  56. // However, calling
  57. //
  58. //        void flowdots::setsettings( const flowparams &theparams);
  59. //
  60. // only makes sense when 'how_often' is unequal to zero. If it is zero (signalling
  61. // that flowdots should figure out itself how often it gets called) flowdots
  62. // recomputes the fixed-point parameters everytime new dot positions must be
  63. // computed, thus overwriting any parameters present.
  64. //
  65. // if how_often        then
  66. // ============     ====
  67. //   == 0.0            use void setsettings( const flowsettings &thesettings);
  68. //     != 0.0            use void setsettings( const flowparams &theparams);
  69. //
  70. // The first one is always safe to use, but slower.
  71. //
  72. class flowparams
  73. {
  74.     protected:
  75.         short x11;
  76.         short x12;
  77.         short x21;
  78.         short x22;
  79.         long  trans_x;
  80.         long  trans_y;
  81. };
  82.  
  83. class flowdots : protected flowparams, public dotcollection,
  84.         public phaser, public flowsettings, public screendots
  85. {
  86.     public:
  87.     
  88.         flowdots( int numbits, int xpos, int ypos,
  89.                 int aantaldots, int lifetime, double how_often = 0.0);
  90.         flowdots( int numbits, screen_position where,
  91.                 int aantaldots, int lifetime, double how_often = 0.0);
  92.  
  93.         void set_how_often( const double how_often);
  94.         //
  95.         // Both the 'setsettings' calls change the actual flow to be shown
  96.         // the one which uses 'flowparams' is faster, because it does not
  97.         // have to do the float-fixed conversion (by calling 'changed').
  98.         // This implies that calling 'changed' after calling
  99.         //        flowdots::setsettings( const flowparams &theparams)
  100.         // is an error since the floating point flow parameters are not
  101.         // changed by that call.
  102.         //
  103.         void setsettings( const flowsettings &thesettings);
  104.         void setsettings( const flowparams &theparams);
  105.         void changed();
  106.  
  107.     protected:
  108.  
  109.         virtual void compute_addresses();
  110.         void apply_flow();
  111.         
  112.         double framerate;
  113.         double updaterate;
  114.         
  115.         int auto_timing;    // flag
  116.         unsigned long time_of_last_apply_flow_call;
  117.         
  118.         void compute_matrices();
  119.         
  120.         static double scale( double orig, double updaterate);
  121.         
  122.     private:
  123.         //
  124.         // we use 'short_long_hack' to split an unsigned long in two
  125.         // signed shorts (the unsigned long being returned by randomizer_step())
  126.         // (could move these to 'dotcollection' and add a member 'uniformize')
  127.         //
  128.         typedef struct two_shorts
  129.         {
  130.             short left;
  131.             short right;
  132.         };
  133.         
  134.         typedef union short_long_hack
  135.         {
  136.             two_shorts shorties;
  137.             unsigned long ulong;
  138.         };
  139. };
  140.  
  141. inline void flowdots::set_how_often( const double how_often)
  142. {
  143.     if( how_often > 0.0)
  144.     {
  145.         auto_timing = false;
  146.         updaterate = how_often;
  147.     } else {
  148.         auto_timing = true;
  149.     }
  150.     time_of_last_apply_flow_call = 0L;
  151. }
  152.  
  153. inline void flowdots::changed()
  154. {
  155.     if( !auto_timing)
  156.     {
  157.         compute_matrices();
  158.     }
  159. }
  160.  
  161. inline double flowdots::scale( double orig, double updaterate)
  162. {
  163.     return( exp( log( orig) / updaterate));
  164. }
  165.